﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Kugar.Core.BaseStruct;
using Kugar.Core.ExtMethod;
using Kugar.Core.Web;
using Kugar.UI.Web.AdminLTE.Enums;
using Kugar.UI.Web.AdminLTE.Helpers;
using Kugar.UI.Web.AdminLTE.PageControls.Helpers.ButtonExtMethod;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging.Abstractions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Kugar.UI.Web.AdminLTE.PageControls.PageCommon
{
    public class PageCommon_Table2<TData> : ContainerBase
    {
        private TableColumns<TData> _columns=null;
        private Lazy<TableSummaryBlock<TData>> _summaryBlock = null;
        private List<TableExtraHeaderRow<TData>> _extraHeaderRows = null;
        private Func<TData, (string name, string value)> _rowHiddenFunc=null;
        private int _index = 0;
        private JObject _currentRowJsonData = null;
        private TData _currentRowData = default;
        private string _id = "";
        internal DataTableTypeEnum _type =AdminLTE.AdminLTEUI.JqTableEndabled? DataTableTypeEnum.jqTable:DataTableTypeEnum.WebUITable;

        private IEnumerable<TData> _data = null;
        private Func<PageCommon_Table2<TData>, string> _rowIDFunc = null;
        private Func<TData, string> _rowCssFactory = null;
        private Func<TData, JObject> _rowDataFactory = null;
        private int _leftFixedColumnCount = 0;
        private int _rightFixedColumnCount = 0;
        private int _fillRowQty = 0;
        private bool _isNoWrap = false;
        private bool _isHideHead = false;
        private int _scrollY = 0;
        private List<string[]> _footers = null;
        private bool _enabledAutoAddRow = false;
        internal int _minFixRow = 1;

        //分页组件
        //private PageCommon_Pager _pager = null;
        private int _recordCount = 0;
        private int _pageSize = 20;
        private int _pageIndex = 1;
        private string _pageKey = "pageIndex";
        private string _pageBoxPlaceHolder = "页码";
        private string _ajaxUrl = "";
        private string _updateElementID = "";
        private (string key, string value)[] _pagerWithExtraArgs = null; //分页组件的额外属性
        private bool _enableLoading = false;
        private bool _isPagerShowFirstLast = false;
        private bool _noFullWidth = false;

        public PageCommon_Table2(ViewContext viewContext) : base(viewContext)
        {
            this.Css("table table-condensed simpletable table-striped table-bordered table-hover layui-form");

            _columns = new TableColumns<TData>(this);

            _summaryBlock=new Lazy<TableSummaryBlock<TData>>(()=>new TableSummaryBlock<TData>(this));

            base.AdminLTEUI.PluginUsaged.DataTables = true;
        }

        public PageCommon_Table2<TData> Data(IEnumerable<TData> dataList)
        {
            _recordCount = 0;
            _data = dataList;
            return this;
        }

        public PageCommon_Table2<TData> Data(IPagedList<TData> dataList)
        {
            _data = dataList?.GetData()??Array.Empty<TData>();
            _recordCount = dataList?.TotalCount??0;
            _pageSize = dataList?.PageSize??0;
            _pageIndex = dataList?.PageIndex??0;

            return this;
        }

        //public PageCommon_Table2<TData> Ajax(string url)
        //{
        //    _isAjax = true;
        //    _ajaxUrl = url;
        //    return this;
        //}

        public PageCommon_Table2<TData> LeftFixedColumn(int fixedCount)
        {
            _leftFixedColumnCount = fixedCount;

            return this;
        }

        public PageCommon_Table2<TData> RightFixedColumn(int fixedCount)
        {
            _rightFixedColumnCount = fixedCount;

            return this;
        }

        public PageCommon_Table2<TData> FillRowCount(int rowQty)
        {
            _fillRowQty = rowQty;

            return this;
        }

        public PageCommon_Table2<TData> DsiabledFullWidth(bool noFullWidth = true)
        {
            _noFullWidth = noFullWidth;

            return this;
        }

        /// <summary>
        /// 设定标题是否取消自动换行,true为不自动换行,false为自动换行
        /// </summary>
        /// <param name="noWrap"></param>
        /// <returns></returns>
        public PageCommon_Table2<TData> NoWrap(bool noWrap = true)
        {
            _isNoWrap = noWrap;

            return this;
        }

        public PageCommon_Table2<TData> HideHead(bool hideHead = true)
        {
            _isHideHead = hideHead;

            return this;
        }

        public PageCommon_Table2<TData> EnabledLoading(bool enableLoading = true)
        {
            _enableLoading = enableLoading;

            return this;
        }

        public PageCommon_Table2<TData> EnabledAutoAddRow(bool enable = true,int minFixRow=1)
        {
            FillRowCount((this._data?.Count() ?? 0) + minFixRow);
            //_minFixRow = minFixRow;
            _enabledAutoAddRow = enable;

            return this;
        }

        public PageCommon_Table2<TData> AddRowHiddenValue(Func<TData,(string name, string value)> rowHiddenFunc)
        {
            _rowHiddenFunc = rowHiddenFunc;

            return this;
        }

        public PageCommon_Table2<TData> AddFooterRow(params string[] cellValues)
        {
            if (_footers==null)
            {
                _footers=new List<string[]>(2);
            }

            _footers.Add(cellValues);

            return this;
        }

        public PageCommon_Table2<TData> PagerWithExtraArgs(params (string key, string value)[] extraArgs)
        {
            _pagerWithExtraArgs = extraArgs;

            return this;
        }

        /// <summary>
        /// 用于分页的查询key
        /// </summary>
        /// <param name="pageIndexKey"></param>
        /// <returns></returns>
        public PageCommon_Table2<TData> PageIndexKey(string pageIndexKey)
        {
            _pageKey = pageIndexKey;

            return this;
        }

        /// <summary>
        /// 分页查询框的placeholder
        /// </summary>
        /// <param name="boxPlaceholder"></param>
        /// <returns></returns>
        public PageCommon_Table2<TData> PageIndexBoxPlaceholder(string boxPlaceholder)
        {
            _pageBoxPlaceHolder = boxPlaceholder;

            return this;
        }

        /// <summary>
        /// 是否显示第一页和最后一页的按钮
        /// </summary>
        /// <param name="isShow"></param>
        /// <returns></returns>
        public PageCommon_Table2<TData> PagerShowFirstLast(bool isShow = true)
        {
            _isPagerShowFirstLast = isShow;

            return this;
        }

        /// <summary>
        /// 使用异步分页获取数据
        /// </summary>
        /// <param name="updateElementID">获取数据后,替换的元素id,必须是id</param>
        /// <param name="actionUrl">获取数据的地址,如果该参数为空,则使用分页控件生成的分页链接进行获取,并根据PageIndexKey参数替换对应的分页页码key</param>
        /// <returns></returns>
        public PageCommon_Table2<TData> AjaxPager(string updateElementID, string actionUrl="")
        {
            _updateElementID = updateElementID;
            _ajaxUrl = actionUrl;

            return this;
        }

        public PageCommon_Table2<TData> RowData(Func<TData, JObject> rowIDFactory)
        {
            _rowDataFactory = rowIDFactory;

            return this;
        }

        public TableColumns<TData> Columns => _columns;

        public TableSummaryBlock<TData> SummaryFooter => _summaryBlock.Value;

        public virtual PageCommon_Table2<TData> RowID(Func<PageCommon_Table2<TData>, string> rowIDFunc)
        {
            _rowIDFunc = rowIDFunc;

            return this;
        }

        public PageCommon_Table2<TData> Type(DataTableTypeEnum type)
        {
            _type = type;

            return this;
        }

        /// <summary>
        /// 使用Y轴滚动的功能
        /// </summary>
        /// <param name="maxHeight">最大高度</param>
        /// <returns></returns>
        public PageCommon_Table2<TData> ScrollY(int maxHeight)
        {
            _scrollY = maxHeight;

            return this;
        }

        public int CurrentRowIndex => _index;

        public JObject CurrentRowJsonData => _rowDataFactory?.Invoke(CurrentRowData);

        public TData CurrentRowData => _currentRowData;

        public string CurrentRowID => _rowIDFunc?.Invoke(this) ?? "";

        public bool IsHideHead => _isHideHead;

        public PageCommon_Table2<TData> RowCss(Func<TData, string> rowCssFactory)
        {
            _rowCssFactory = rowCssFactory;

            return this;
        }

        public IEnumerable<TData> GetData()
        {
            return _data;
        }

        /// <summary>
        /// 添加额外的表头行
        /// </summary>
        /// <returns></returns>
        public PageCommon_Table2<TData> AddExtraColumnRow(Action<TableExtraHeaderRow<TData>> configFunc)
        {
            var row=new TableExtraHeaderRow<TData>(this);
            configFunc(row);

            _extraHeaderRows = (_extraHeaderRows ?? new List<TableExtraHeaderRow<TData>>(2));

            _extraHeaderRows.Add(row);

            return this;
        }



        internal override ContainerBase RenderInternal()
        {

            var disabledjqTable = ((bool?)ViewContext.ViewData.TryGetValue("DisabledjqTable", false)) == true;

            if (disabledjqTable)
            {
                _type = DataTableTypeEnum.WebUITable;
            }

            if (_type== DataTableTypeEnum.jqTable)
            {
                Attributes.Class("jqtable");
            }
            else
            {
                Attributes.Class("webui_table");
            }

            if (!_noFullWidth)
            {
                Attributes.Class("fullwidth");
            }

            if (_leftFixedColumnCount>0)
            {
                Attributes.Data("data-leftfixed", _leftFixedColumnCount.ToStringEx());
            }

            if (_rightFixedColumnCount>0)
            {
                Attributes.Data("data-rightfixed", _rightFixedColumnCount.ToStringEx());
            }

            if (_scrollY>0)
            {
                Attributes.Data("data-scrolly", _scrollY.ToStringEx());
            }

            if (_isNoWrap)
            {
                Attributes.Class("nowrap");
            }

            //if (_enabledAutoAddRow)
            {
                Attributes.Data("data-enabledautoaddrow", _enabledAutoAddRow.ToString().ToLower());
            }


            _id = Attributes.GetValue("id", "");

            if (string.IsNullOrWhiteSpace(_id))
            {
                _id = "tbl_" + AdminLTEUI.NextControlIndex();

                Attributes.ID(_id);
            }

            if (_withOuterBorder)
            {
                ViewContext.Writer.WriteLine($"<div class=\"{_outerBorderCss}\">");
            }

            if (_type == DataTableTypeEnum.jqTable)
            {
                ViewContext.Writer.WriteLine($"<div class=\"{_enableLoading.If("box", "")} tablewrapper\">");
            }

            ViewContext.Writer.WriteLine("<div>");
            ViewContext.Writer.WriteLine($"<table {Attributes} {(_type== DataTableTypeEnum.jqTable? "style=\"width:100%\"" : "" )}>");

            return this;
        }

        public override void Dispose()
        {
            _index = -1;

            if (_columns._columns.HasData())
            {
                if (!_isHideHead)
                {
                    ViewContext.Writer.WriteLine($"<thead style=\"{(_isHideHead ? "display:none;" : "")}\">");

                    //_columns._columns.Where(x=>!string.IsNullOrEmpty(x._width))

                    if (_extraHeaderRows.HasData())
                    {
                        foreach (var headerRow in _extraHeaderRows)
                        {
                            headerRow.Render(ViewContext);
                        }
                    }

                    ViewContext.Writer.WriteLine("<tr class=\"realTableHeader\">");
                    foreach (var column in _columns._columns)
                    {
                        if (column._isHide)
                        {
                            continue;
                        }

                        ViewContext.Writer.WriteLine(column.RenderHeader());
                    }

                    ViewContext.Writer.WriteLine("</tr>");
                    ViewContext.Writer.WriteLine("</thead>");
                }
                

                ViewContext.Writer.WriteLine("<tbody>");

                var datalist = _data.ToArrayEx();

                var maxIndex = Math.Max(datalist.Length, _fillRowQty);

                for (int i = 0; i < maxIndex; i++)
                {
                    TData data;

                    if (i <= datalist.Length - 1)
                    {
                        data = datalist[i];
                    }
                    else
                    {
                        data = default(TData);
                    }

                    var rowCss = _rowCssFactory?.Invoke(data);
                    ViewContext.Writer.WriteLine($"<tr {rowCss.IfNotEmptyOrWhileSpace($"class=\"{rowCss}\"")}>");

                    if (_rowHiddenFunc!=null)
                    {
                        var rowData = _rowHiddenFunc(data);
                        ViewContext.Writer.WriteLine($"<input type=\"hidden\" name=\"{rowData.name}\" value=\"{rowData.value}\" />");
                    }

                    _currentRowData = data;
       
                    _index++;

                    foreach (var column in _columns._columns)
                    {
                        if (column._isHide)
                        {
                            continue;
                        }

                        //var widthStyle = $"{(string.IsNullOrWhiteSpace(column._width) ? "" : $"width:{column._width};")}{(string.IsNullOrWhiteSpace(column._minWidth) ? "" : $"min-width:{column._minWidth};")}{(string.IsNullOrWhiteSpace(column._maxWidth) ? "" : $"max-width:{column._maxWidth};")}";

                        var cellCss = column._cellCss;
                        ViewContext.Writer.WriteLine($"<td {cellCss.IfNotEmptyOrWhileSpace($"class=\"{cellCss}\"")}>");

                        ViewContext.Writer.WriteLine($"<div class=\"webui_data_cell\" >");

                        //if (column._cellStyleFactory != null)
                        //{
                        //    ViewContext.Writer.Write(" style=\"");

                        //    ViewContext.Writer.WriteLine(column._cellStyleFactory(data));

                        //    ViewContext.Writer.Write("\" ");
                        //}


                        //ViewContext.Writer.Write(" >");

                        if (column._hideValueFactory!=null)
                        {
                            var values = column._hideValueFactory(data);

                            foreach (var hiddenValue in values)
                            {
                                ViewContext.Writer.WriteLine($"<input type=\"hidden\" name=\"{hiddenValue.name}\" value=\"{hiddenValue.value}\" />");
                            }
                        }

                        column.RenderContent(data, ViewContext.Writer);

                        //ViewContext.Writer.WriteLine("<div class=\"clearfix\"></div>");

                        //ViewContext.Writer.WriteLine("<div class=\"field-errormsg\"></div>");

                        ViewContext.Writer.WriteLine("</div>");

                        ViewContext.Writer.WriteLine("</td>");
                    }

                    ViewContext.Writer.WriteLine("</tr>");
                }

                ViewContext.Writer.WriteLine("</tbody>");
            }

            if (_footers.HasData())
            {
                ViewContext.Writer.WriteLine("<tfoot >");

                foreach (var footer in _footers)
                {
                    ViewContext.Writer.WriteLine("<tr>");

                    foreach (var cell in footer)
                    {
                        ViewContext.Writer.WriteLine("<td>");
                        ViewContext.Writer.Write(cell);
                        ViewContext.Writer.WriteLine("</td>");
                    }

                    ViewContext.Writer.WriteLine("</tr>");
                }

                ViewContext.Writer.WriteLine("</tfoot>");
            }

            ViewContext.Writer.WriteLine("</table>");

            

            if (_type == DataTableTypeEnum.jqTable)
            {
                if (_enableLoading)
                {
                    ViewContext.Writer.WriteLine("<div class=\"overlay\"><i class=\"fa fa-refresh fa-spin\"></i></div>");
                }

                ViewContext.Writer.WriteLine("</div> <!-- .tablewrapper -->");
            }
            

            if (_recordCount>0)
            {
                ViewContext.Writer.WriteLine("<div class=\"tablepagination\">");

                var modalID = ViewContext.ViewData.TryGetValue("ModalWindowID", "").ToStringEx();

                if (string.IsNullOrWhiteSpace(_updateElementID) && !string.IsNullOrWhiteSpace(modalID))
                {
                    _updateElementID = modalID;
                }

                var pager=new PageCommon_Pager(ViewContext);
                pager.CurrentIndex(_pageIndex).PageIndexParameterName(_pageKey).BoxPlaceholder(_pageBoxPlaceHolder).ShowFirstLast(_isPagerShowFirstLast).PageSize(_pageSize)
                    .RecordCount(_recordCount)
                    .UpdateElementID(_updateElementID,_ajaxUrl)
                    .WithExtraArgs(_pagerWithExtraArgs)
                    .ForControlID(_id)
                    ;

                ViewContext.Writer.WriteLine(pager.Css("pull-right").Render().ToStringEx());

                WriteClearfix();

                ViewContext.Writer.WriteLine("</div>");
            }

            WriteClearfix();

            if (_withOuterBorder)
            {
                ViewContext.Writer.WriteLine($"</div> <!-- outer border -->");
            }

            ViewContext.Writer.WriteLine("</div>");

            WriteClearfix();
        }

        public static PageCommon_Table2<TData> operator +(PageCommon_Table2<TData> tbl, ColumnBase<TData> col2)
        {
            tbl.Columns.AddColumn(col2);

            return tbl;
        }
    }

    public class TableExtraHeaderRow<TData>
    {
        private List<TableExtraHeaderCell> _cells=new List<TableExtraHeaderCell>();
        private TagAttrbute _tagAttrbute = null;
        private PageCommon_Table2<TData> _table=null;

        public TableExtraHeaderRow(PageCommon_Table2<TData> table)
        {
            _table = table;

            _tagAttrbute =new TagAttrbute();

            _tagAttrbute.Class("extraHeaderRow");
        }

        public TableExtraHeaderRow<TData> AddCell(string text,int colSpan=1,Action<TagAttrbute> attrConfig=null)
        {
            var cell = new TableExtraHeaderCell();
            cell.Text = text;
            cell.Colspan = colSpan;

            if (attrConfig!=null)
            {
                var attr=new TagAttrbute();
                attrConfig(attr);

                cell.Attributes = attr;
            }

            _cells.Add(cell);

            return this;
        }

        public void Render(ViewContext viewContext)
        {
            var writer = viewContext.Writer;

            writer.WriteLine($"<tr {_tagAttrbute}>");

            foreach (var cell in _cells)
            {
                writer.WriteLine($"<th {(cell.Colspan>1?$"colspan=\"{cell.Colspan}\"":"")} {cell.Attributes.ToStringEx()}>{cell.Text}</th>");
            }

            var cellColSpan = _cells.Sum(x => x.Colspan);

            if (cellColSpan < _table.Columns.Count)
            {
                for (int i = 0; i < _table.Columns.Count- cellColSpan; i++)
                {
                    writer.WriteLine($"<th></th>");
                }
            }

            writer.WriteLine("</tr>");
        }

        /// <summary>
        /// 多层表头单元格
        /// </summary>
        private class TableExtraHeaderCell
        {
            public string Text { set; get; }

            public TagAttrbute Attributes { set; get; }

            public int Colspan { set; get; } = 1;
        }
    }

    public class TableColumns<TData>
    {
        internal List<ColumnBase<TData>> _columns = new List<ColumnBase<TData>>();
        private PageCommon_Table2<TData> _table = null;

        public TableColumns(PageCommon_Table2<TData> table)
        {
            _table = table;
        }

        public void AddColumn(ColumnBase<TData> column)
        {
            _columns.Add(column);
        }

        public int Count => _columns.Count;

        public PageCommon_Table2<TData> Table => _table;
    }

    public class TableSummaryBlock<TData>
    {
        internal List<TableFooter_ItemBase<TData>> _items=new List<TableFooter_ItemBase<TData>>(3);

        public TableSummaryBlock(PageCommon_Table2<TData> table)
        {
            Table = table;
        }

        public void AddItem(TableFooter_ItemBase<TData> item)
        {
            _items.Add(item);
        }
        
        public PageCommon_Table2<TData> Table { get; private set; }
    }



    /// <summary>
    /// 合计行
    /// </summary>
    public class TableFooterRow<TData>
    {
        private List<TableFooter_ItemBase<TData>> _lst=new List<TableFooter_ItemBase<TData>>();
        private PageCommon_Table2<TData> _table = null;

        public TableFooterRow(PageCommon_Table2<TData> table)
        {
            _table = table;
        }

        public TableFooterRow<TData> AddItem(TableFooter_ItemBase<TData> item)
        {
            _lst.Add(item);

            return this;
        }

        public void Render()
        {
            if (_lst.HasData())
            {
                _table.ViewContext.Writer.WriteLine("<tr>");

                foreach (var item in _lst)
                {
                    _table.ViewContext.Writer.WriteLine("<td>");

                    item.Render();

                    _table.ViewContext.Writer.WriteLine("<td>");
                }

                _table.ViewContext.Writer.WriteLine("</tr>");
            }

            
        }
    }

    public abstract class TableFooter_ItemBase<TData>:AdminLTEElementBase
    {
        private PageCommon_Table2<TData> _table = null;

        protected TableFooter_ItemBase(TableFooterRow<TData> row, ViewContext viewContext) : base(viewContext)
        {
        }

        protected PageCommon_Table2<TData> Table => _table;

        public abstract void Render();

        public override string ToString()
        {
            return "";
        }
    }

    public class TableFooter_Value<TData> : TableFooter_ItemBase<TData>
    {
        private string _label = "";
        private string _value = "";

        public TableFooter_Value(PageCommon_Table2<TData> table, ViewContext viewContext) : base(null, viewContext)
        {
        }

        public TableFooter_Value<TData> SetLabel(string label)
        {
            _label = label;

            return this;
        }

        public TableFooter_Value<TData> SetValue(string value)
        {
            _value = value;

            return this;
        }

        public override void Render()
        {
            throw new NotImplementedException();
        }
    }

    #region 表格列

    public abstract class ColumnBase : AdminLTEElementBase
    {
        internal bool _unsizable = false;
        internal string _width = "";
        internal string _minWidth = "";
        internal string _maxWidth = "";
        internal string _title = "&nbsp;";
        internal string _thCss = "";
        internal string _cellCss = "";
        internal TagAttrbute _headCellAttr = null;
        internal string _sortKey = "";
        internal ColumnSortTypeEnum _sortType = ColumnSortTypeEnum.unsort;

        internal bool _isHide = false;

        protected ColumnBase(ViewContext viewContext) : base(viewContext)
        {
        }


        public override string ToString()
        {
            return "";
        }

        public static implicit operator string(ColumnBase d)
        {
            return d.ToStringEx();
        }
    }



    //public delegate IEnumerable<(string name, string value)> HiddenValueFactory<TData>(TData column);

    public abstract class ColumnBase<TData> : ColumnBase
    {
        //internal Func<TData, string> _cellCssFactory = null;
        internal string _cellCss = "";
        //internal Func<TData, string> _cellStyleFactory = null;

        private PageCommon_Table2<TData> _table = null;
        
        internal Func<TData, IEnumerable<(string name, string value)>> _hideValueFactory = null;
        //internal List<(string name, string value)> _hiddenValues = new List<(string name, string value)>();
        

        protected ColumnBase(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext)
        {
            _table = table;
        }


        public TData CurrentData => Table.CurrentRowData;

        public abstract void RenderContent(TData data, TextWriter writer);

        public virtual string RenderHeader()
        {
            //var json = new JObject()
            //           {
            //               ["field"] = $"field_{this.AdminLTEUI.NextControlIndex()}"
            //           };

            //if (!string.IsNullOrEmpty(_width))
            //{
            //    json["width"] = _width;
            //}

            //if (_unsizable)
            //{
            //    json["unresize"] = _unsizable;
            //}

            //if (_fixed != ColumnFixedType.none)
            //{
            //    json["fixed"] = _fixed.ToStringEx();
            //}

            //if (_alignType == ColumnAlignType.left)
            //{
            //    json["align"] = _alignType.ToStringEx();                              
            //}

            
            if (!string.IsNullOrWhiteSpace(_sortKey) && Table._type== DataTableTypeEnum.WebUITable)
            {
                _title += $" <i class=\"head-sort-icon fa {sortTypeToString(_sortType)}\" data-sortkey=\"{_sortKey}\"></i>";
            }

            if (_headCellAttr!=null)
            {
                _headCellAttr.Class(_thCss);

                if (!string.IsNullOrEmpty(_width))
                {
                    _headCellAttr.Style("width", _width.ToStringEx());
                }

                if (!string.IsNullOrEmpty(_minWidth))
                {
                    _headCellAttr.Style("min-width", _minWidth.ToStringEx());
                }

                if (!string.IsNullOrEmpty(_maxWidth))
                {
                    _headCellAttr.Style("max-width", _maxWidth.ToStringEx());
                }

                return $"<th {_headCellAttr}>{_title}</th>";
            }

            var style = $"style=\"{(string.IsNullOrWhiteSpace(_width) ? "" : $"width:{_width};")}{(string.IsNullOrWhiteSpace(_minWidth) ? "" : $"min-width:{_minWidth};")}{(string.IsNullOrWhiteSpace(_maxWidth) ? "" : $"max-width:{_maxWidth};")}\"";

            return $"<th class=\"{_thCss}\" {style}>{_title}</th>";
        }

        private string sortTypeToString(ColumnSortTypeEnum type)
        {
            switch (type)
            {
                case ColumnSortTypeEnum.unsort:
                    return "fa-sort";
                case ColumnSortTypeEnum.asc:
                    return "fa-sort-amount-asc";
                case ColumnSortTypeEnum.desc:
                    return "fa-sort-amount-desc";
                default:
                    throw new ArgumentOutOfRangeException(nameof(type), type, null);
            }
        }

        public PageCommon_Table2<TData> Table => _table;

        public override string ToString()
        {
            return "";
        }

        public static ColumnBase<TData> operator +(ColumnBase<TData> col1, ColumnBase<TData> col2)
        {
            col1.Table.Columns.AddColumn(col2);

            return col1;
        }
    }

    public class TableColumn_Index<TData> : ColumnBase<TData>
    {
        public TableColumn_Index(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext, table)
        {
            _unsizable = true;
            _width = "10px";
            _title = "#";
        }

        public TableColumn_Index<TData> WithHiddenValues(Func<TData, IEnumerable<(string name, string value)>> hiddenFunc)
        {
            _hideValueFactory = hiddenFunc;

            return this;
        }

        public TableColumn_Index<TData> WithHiddenValue(Func<TData, (string name, string value)> hiddenValueFunc)
        {
            if (hiddenValueFunc == null)
            {
                throw new ArgumentNullException(nameof(hiddenValueFunc));
            }

            WithHiddenValues(data => new[] { hiddenValueFunc(data) });

            return this;
        }

        public override void RenderContent(TData data, TextWriter writer)
        {
            writer.WriteLine($"<span class=\"rowindexcell\">{Table.CurrentRowIndex + 1}</span>");
        }

        public override string RenderHeader()
        {
            if (string.IsNullOrWhiteSpace(_width))
            {
                _width = "15px";
            }

            if (_headCellAttr != null)
            {
                _headCellAttr.Class("indexcol");
                _headCellAttr.Class(_thCss);

                if (!string.IsNullOrEmpty(_width))
                {
                    _headCellAttr.Style("width", _width.ToStringEx());
                }

                if (!string.IsNullOrEmpty(_minWidth))
                {
                    _headCellAttr.Style("min-width", _minWidth.ToStringEx());
                }

                if (!string.IsNullOrEmpty(_maxWidth))
                {
                    _headCellAttr.Style("max-width", _maxWidth.ToStringEx());
                }

                return $"<th {_headCellAttr}><span>#</span></th>";
            }

            var style = $"style=\"{(string.IsNullOrWhiteSpace(_width) ? "" : $"width:{_width};")}{(string.IsNullOrWhiteSpace(_minWidth) ? "" : $"min-width:{_minWidth};")}{(string.IsNullOrWhiteSpace(_maxWidth) ? "" : $"max-width:{_maxWidth};")}\"";

            return $"<th class=\"indexcol {_thCss}\" {style}><span>#</span></th>";
            //return ;
        }
    }

    public class TableColumn_Label<TData> : ColumnBase<TData>
    {
        private Func<TData, string> _valueFactory = null;

        public TableColumn_Label(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext, table)
        {
        }

        public TableColumn_Label<TData> Value(Func<TData, string> valueFactory)
        {
            _valueFactory = (data) => valueFactory(data);

            return this;
        }

        public TableColumn_Label<TData> Value(Func<TData, HelperResult> valueFactory)
        {
            _valueFactory = (data) => valueFactory(data).ToHtmlString().ToStringEx();

            return this;
        }

        public TableColumn_Label<TData> WithHiddenValues(Func<TData, IEnumerable<(string name, string value)>> hiddenFunc)
        {
            _hideValueFactory = hiddenFunc;

            return this;
        }

        /// <summary>
        /// 包含一个隐藏数据字段
        /// </summary>
        /// <param name="hiddenValueFunc"></param>
        /// <returns></returns>
        public TableColumn_Label<TData> WithHiddenValue(Func<TData, (string name, string value)> hiddenValueFunc)
        {
            if (hiddenValueFunc == null)
            {
                throw new ArgumentNullException(nameof(hiddenValueFunc));
            }

            WithHiddenValues(data => new[] { hiddenValueFunc(data) });

            return this;
        }

        public override void RenderContent(TData data, TextWriter writer)
        {
            var value = _valueFactory(data);

            var hasSetWidth = !string.IsNullOrWhiteSpace(this._width) ||
                              !string.IsNullOrWhiteSpace(this._minWidth) ||
                              !string.IsNullOrWhiteSpace(this._maxWidth);


            writer.Write($"<span class=\"webui_data_cell_labelValue {(hasSetWidth?"withWidth":"")}\">{value}</span>");
        }
    }

    public class TableColumn_Textbox<TData> : ColumnBase<TData>
    {
        private Func<TData, string> _valueFactory = null;
        private Func<TData, string> _nameFactory = null;
        private Func<TData, bool> _requireFactory = null;
        private Func<TData, string> _placeHolder = null;
        private Func<TData, string> _idFactory = null;
        private Func<TData, bool> _readonlyFactory = null;
        private Func<TData, InputElementType> _typeFactory = x => InputElementType.text;
        private Func<TData, string> _minValueFunc = null;
        private Func<TData, string> _maxValueFunc = null;

        public TableColumn_Textbox(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext, table)
        {
        }

        public TableColumn_Textbox<TData> Value(Func<TData, string> valueFactory)
        {
            _valueFactory = (data) => valueFactory(data);

            return this;
        }

        public TableColumn_Textbox<TData> Name(Func<TData, string> nameFactory)
        {
            _nameFactory = nameFactory;

            return this;
        }

        public TableColumn_Textbox<TData> Name(string name)
        {
            _nameFactory = x => name;

            return this;
        }

        public TableColumn_Textbox<TData> Type(Func<TData, InputElementType> typeFactory)
        {
            _typeFactory = typeFactory;

            return this;
        }

        public TableColumn_Textbox<TData> Type(InputElementType type)
        {
            _typeFactory = x => type;

            return this;
        }

        public TableColumn_Textbox<TData> Require(Func<TData, bool> requireFactory)
        {
            _requireFactory = requireFactory;

            return this;
        }

        public TableColumn_Textbox<TData> Placeholder(Func<TData, string> placeHolder)
        {
            _placeHolder = placeHolder;

            return this;
        }

        public TableColumn_Textbox<TData> PlaceHolder(string placeHolder)
        {
            _placeHolder = (data) => placeHolder;

            return this;
        }

        public TableColumn_Textbox<TData> ID(Func<TData, string> idFactory)
        {
            _idFactory = idFactory;

            return this;
        }

        public TableColumn_Textbox<TData> ReadOnly(Func<TData, bool> readOnlyFunc)
        {
            _readonlyFactory = readOnlyFunc;
            return this;
        }

        public TableColumn_Textbox<TData> ReadOnly(bool readOnly)
        {
            _readonlyFactory = x=> readOnly;
            return this;
        }

        public TableColumn_Textbox<TData> ValueLimit(string minValue, string maxValue = "")
        {
            return this.ValueLimit(x => minValue, x => maxValue);
        }

        public TableColumn_Textbox<TData> ValueLimit(Func<TData,string> minValueFunc, Func<TData, string> maxValuFunc = null)
        {
            _minValueFunc = minValueFunc;
            _maxValueFunc = maxValuFunc;

            return this;
        }

        public TableColumn_Textbox<TData> WithHiddenValues(Func<TData, IEnumerable<(string name, string value)>> hiddenFunc)
        {
            _hideValueFactory = hiddenFunc;

            return this;
        }

        /// <summary>
        /// 包含一个隐藏数据字段
        /// </summary>
        /// <param name="hiddenValueFunc"></param>
        /// <returns></returns>
        public TableColumn_Textbox<TData> WithHiddenValue(Func<TData, (string name, string value)> hiddenValueFunc)
        {
            if (hiddenValueFunc == null)
            {
                throw new ArgumentNullException(nameof(hiddenValueFunc));
            }

            WithHiddenValues(data => new[] { hiddenValueFunc(data) });

            return this;
        }

        public override void RenderContent(TData data, TextWriter writer)
        {
            if (_typeFactory == null)
            {
                _typeFactory = x => InputElementType.text;
            }

            var value = _valueFactory?.Invoke(data);

            try
            {
                var id = _idFactory?.Invoke(data);

                writer.Write($"<input type=\"{_typeFactory(data)}\" lay-ignore class=\"form-control textbox cell-textbox\" {(string.IsNullOrWhiteSpace(id) ? "" : $"id=\"{id}\"")} name=\"{_nameFactory?.Invoke(data)}\" value=\"{value.ToStringEx()}\" placeholder='{_placeHolder?.Invoke(data).ToStringEx()}' {(_requireFactory?.Invoke(data) == true ? $"required='required'" : "")} {(_minValueFunc==null?"":$"min='{_minValueFunc(data)}'")} {(_maxValueFunc == null ? "" : $"max='{_maxValueFunc(data)}'")} {(_readonlyFactory?.Invoke(data) == true ? $"readonly='readonly'" : "")}> ");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

        }
    }

    public class TableColumn_Checkbox<TData> : ColumnBase<TData>
    {
        private Func<TData, bool> _checkedFunc = null;
        private Func<TData, string> _valueFactory = null;
        private Func<TData, string> _nameFactory = null;
        private Func<TData, string> _idFactory = null;
        private Func<TData, string> _label = null;
        private Func<TData, bool> _disabled = null;
        private bool _isHideSelectAll = false;

        public TableColumn_Checkbox(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext, table)
        {
        }

        public TableColumn_Checkbox<TData> Name(Func<TData, string> nameFactory)
        {
            _nameFactory = nameFactory;

            return this;
        }

        public TableColumn_Checkbox<TData> Name(string name)
        {
            _nameFactory = x => name;

            return this;
        }

        /// <summary>
        /// 复选框value属性的值
        /// </summary>
        /// <param name="valueFactory"></param>
        /// <returns></returns>
        public TableColumn_Checkbox<TData> Value(Func<TData, string> valueFactory)
        {
            _valueFactory = (data) => valueFactory(data);

            return this;
        }

        /// <summary>
        /// 复选框的ID
        /// </summary>
        /// <param name="idFactory"></param>
        /// <returns></returns>
        public TableColumn_Checkbox<TData> Id(Func<TData, string> idFactory)
        {
            _idFactory = idFactory;

            return this;
        }

        /// <summary>
        /// 该复选框是否选中
        /// </summary>
        /// <param name="checkedFactory"></param>
        /// <returns></returns>
        public TableColumn_Checkbox<TData> Checked(Func<TData, bool> checkedFactory)
        {
            _checkedFunc = checkedFactory;

            return this;
        }

        /// <summary>
        /// 复选框的文字标签
        /// </summary>
        /// <param name="labelFactory"></param>
        /// <returns></returns>
        public TableColumn_Checkbox<TData> Label(Func<TData, string> labelFactory)
        {
            _label = labelFactory;

            return this;
        }

        /// <summary>
        /// 单元格内的复选框是否禁用
        /// </summary>
        /// <param name="disabledFactory"></param>
        /// <returns></returns>
        public TableColumn_Checkbox<TData> Disabled(Func<TData, bool> disabledFactory)
        {
            _disabled = disabledFactory;

            return this;
        }

        public TableColumn_Checkbox<TData> WithHiddenValues(Func<TData, IEnumerable<(string name, string value)>> hiddenFunc)
        {
            _hideValueFactory = hiddenFunc;

            return this;
        }

        /// <summary>
        /// 包含一个隐藏数据字段
        /// </summary>
        /// <param name="hiddenValueFunc"></param>
        /// <returns></returns>
        public TableColumn_Checkbox<TData> WithHiddenValue(Func<TData, (string name, string value)> hiddenValueFunc)
        {
            if (hiddenValueFunc == null)
            {
                throw new ArgumentNullException(nameof(hiddenValueFunc));
            }

            WithHiddenValues(data => new[] { hiddenValueFunc(data) });

            return this;
        }

        public TableColumn_Checkbox<TData> HideSelectAll(bool isHideSelectAll = true)
        {
            _isHideSelectAll = isHideSelectAll;

            return this;
        }

        public override void RenderContent(TData data, TextWriter writer)
        {
            var id = _idFactory?.Invoke(data);

            writer.Write(
                $"<input type=\"checkbox\" {(string.IsNullOrWhiteSpace(id) ? "" : $"id=\"{id}\"")} value=\"{(_valueFactory?.Invoke(data))}\" name=\"{_nameFactory?.Invoke(data)}\" title=\"{_label?.Invoke(data)}\" lay-skin=\"primary\" {(_checkedFunc?.Invoke(data) == true ? "checked" : "")} {(_disabled?.Invoke(data) == true ? "disabled" : "")}>");
        }

        public override string RenderHeader()
        {
            if (_title == "&nbsp;")
            {
                _title = "";
            }

            if ((string.IsNullOrWhiteSpace(_title) || Table.IsHideHead) && _label == null && string.IsNullOrWhiteSpace(_width))
            {
                _width = "20px";
            }

            var selectAll = $"<input type=\"checkbox\" class=\"selectall\" lay-skin=\"primary\">";

            if (_headCellAttr != null)
            {
                _headCellAttr.Class("selectcol");
                _headCellAttr.Class(_thCss);

                if (!string.IsNullOrEmpty(_width))
                {
                    _headCellAttr.Style("width", _width.ToStringEx());
                }

                if (!string.IsNullOrEmpty(_minWidth))
                {
                    _headCellAttr.Style("min-width", _minWidth.ToStringEx());
                }

                if (!string.IsNullOrEmpty(_maxWidth))
                {
                    _headCellAttr.Style("max-width", _maxWidth.ToStringEx());
                }

                return $"<th {_headCellAttr}><span>{(_isHideSelectAll ? "" : selectAll)} {_title}</span></th>";
            }

            var style = $"style=\"{(string.IsNullOrWhiteSpace(_width) ? "" : $"width:{_width};")}{(string.IsNullOrWhiteSpace(_minWidth) ? "" : $"min-width:{_minWidth};")}{(string.IsNullOrWhiteSpace(_maxWidth) ? "" : $"max-width:{_maxWidth};")}\"";

            return $"<th {style} class=\"selectcol {_thCss}\">{(_isHideSelectAll?"": selectAll)} {_title}</th>";
        }
    }

    public class TableColumn_Radio<TData> : ColumnBase<TData>
    {
        private Func<TData, bool> _checkedFunc = null;
        private Func<TData, string> _valueFactory = null;
        private Func<TData, string> _nameFactory = null;
        private Func<TData, string> _idFactory = null;
        private Func<TData, string> _label = null;
        private Func<TData, bool> _disabled = null;

        public TableColumn_Radio(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext, table)
        {
        }

        public TableColumn_Radio<TData> Name(Func<TData, string> nameFactory)
        {
            _nameFactory = nameFactory;

            return this;
        }

        public TableColumn_Radio<TData> Name(string name)
        {
            _nameFactory = x => name;

            return this;
        }

        /// <summary>
        /// 单选框value属性的值
        /// </summary>
        /// <param name="valueFactory"></param>
        /// <returns></returns>
        public TableColumn_Radio<TData> Value(Func<TData, string> valueFactory)
        {
            _valueFactory = valueFactory;

            return this;
        }

        /// <summary>
        /// 单选框的ID
        /// </summary>
        /// <param name="idFactory"></param>
        /// <returns></returns>
        public TableColumn_Radio<TData> Id(Func<TData, string> idFactory)
        {
            _idFactory = idFactory;

            return this;
        }

        /// <summary>
        /// 该单选框是否选中
        /// </summary>
        /// <param name="checkedFactory"></param>
        /// <returns></returns>
        public TableColumn_Radio<TData> Checked(Func<TData, bool> checkedFactory)
        {
            _checkedFunc = checkedFactory;

            return this;
        }

        /// <summary>
        /// 单选框的文字标签
        /// </summary>
        /// <param name="labelFactory"></param>
        /// <returns></returns>
        public TableColumn_Radio<TData> Label(Func<TData, string> labelFactory)
        {
            _label = labelFactory;

            return this;
        }

        public TableColumn_Radio<TData> WithHiddenValues(Func<TData, IEnumerable<(string name, string value)>> hiddenFunc)
        {
            _hideValueFactory = hiddenFunc;

            return this;
        }

        /// <summary>
        /// 包含一个隐藏数据字段
        /// </summary>
        /// <param name="hiddenValueFunc"></param>
        /// <returns></returns>
        public TableColumn_Radio<TData> WithHiddenValue(Func<TData, (string name, string value)> hiddenValueFunc)
        {
            if (hiddenValueFunc == null)
            {
                throw new ArgumentNullException(nameof(hiddenValueFunc));
            }

            WithHiddenValues(data => new[] { hiddenValueFunc(data) });

            return this;
        }

        /// <summary>
        /// 单元格内的单选框是否禁用
        /// </summary>
        /// <param name="disabledFactory"></param>
        /// <returns></returns>
        public TableColumn_Radio<TData> Disabled(Func<TData, bool> disabledFactory)
        {
            _disabled = disabledFactory;

            return this;
        }

        public override void RenderContent(TData data, TextWriter writer)
        {
            var id = _idFactory?.Invoke(data);

            writer.Write(
                $"<input type=\"radio\" {(string.IsNullOrWhiteSpace(id) ? "" : $"id=\"{id}\"")} value='{(_valueFactory?.Invoke(data))}' name=\"{_nameFactory?.Invoke(data)}\" title=\"{_label?.Invoke(data)}\" lay-skin=\"primary\" {(_checkedFunc?.Invoke(data) == true ? "checked" : "")} {(_disabled?.Invoke(data) == true ? "disabled" : "")}>");
        }
    }

    public class TableColumn_Selector<TData> : ColumnBase<TData>
    {
        private Func<TData, string> _nameFactory = null;
        private IEnumerable<SelectorItem> _options = null;
        private SelectorItem _firstItem = null;
        private Func<TData, string> _idFactory = null;
        private Func<TData, bool> _disabled = null;
        private string _onChangedScript = "";
        private Func<TData, string> _selectedValue = null;


        public TableColumn_Selector(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext, table)
        {
        }

        public TableColumn_Selector<TData> Name(Func<TData, string> nameFactory)
        {
            _nameFactory = nameFactory;

            return this;
        }

        public TableColumn_Selector<TData> Name(string name)
        {
            _nameFactory = x => name;

            return this;
        }

        /// <summary>
        /// 单选框的ID
        /// </summary>
        /// <param name="idFactory"></param>
        /// <returns></returns>
        public TableColumn_Selector<TData> Id(Func<TData, string> idFactory)
        {
            _idFactory = idFactory;

            return this;
        }

        public TableColumn_Selector<TData> Options(IEnumerable<SelectorItem> options)
        {
            _options = options;

            return this;
        }

        public TableColumn_Selector<TData> Options<TEnumableData>(IEnumerable<TEnumableData> optionsGetter,
            Func<TEnumableData, string> titleGetter, Func<TEnumableData, string> valueGetter,
            Func<TEnumableData, bool> disabledGetter = null)
        {
            _options = optionsGetter.Select(x =>
                new SelectorItem(titleGetter(x), valueGetter(x), disabledGetter?.Invoke(x) ?? false));

            return this;
        }

        /// <summary>
        /// 选项列表,根据枚举类型
        /// </summary>
        /// <param name="enumType"></param>
        /// <returns></returns>
        public TableColumn_Selector<TData> Options(Type enumType, Func<string, bool> disabledGetter = null)
        {
            if (!enumType.IsEnum)
            {
                throw new ArrayTypeMismatchException("enumType参数类型必须为枚举类型");
            }

            var names = enumType.GetEnumNames();
            var values = (int[]) enumType.GetEnumValues();

            var lst = new List<SelectorItem>(names.Length);

            for (int i = 0; i < names.Length; i++)
            {
                FieldInfo enumInfo = enumType.GetField(names[i]);

                var a = (DescriptionAttribute) enumInfo.GetCustomAttributes(typeof(DescriptionAttribute), false)
                    .FirstOrDefault();

                var k = new SelectorItem(a != null ? a.Description : names[i].ToStringEx(), values[i].ToString(),
                    disabledGetter?.Invoke(values[i].ToString()) ?? false);

                lst.Add(k);
            }

            _options = lst;

            return this;
        }

        public TableColumn_Selector<TData> CurrentValue(Func<TData, string> selectedValue)
        {
            _selectedValue = selectedValue;

            return this;
        }

        /// <summary>
        /// 单元格内的下拉框是否禁用
        /// </summary>
        /// <param name="disabledFactory"></param>
        /// <returns></returns>
        public TableColumn_Selector<TData> Disabled(Func<TData, bool> disabledFactory)
        {
            _disabled = disabledFactory;

            return this;
        }

        public TableColumn_Selector<TData> Disabled(bool disabled)
        {
            _disabled = x => disabled;

            return this;
        }

        /// <summary>
        /// 额外真在Options首个备选项前的选项
        /// </summary>
        /// <param name="firstItem"></param>
        /// <returns></returns>
        public TableColumn_Selector<TData> FirstItem(SelectorItem firstItem)
        {
            _firstItem = firstItem;

            return this;
        }

        public TableColumn_Selector<TData> WithHiddenValues(Func<TData, IEnumerable<(string name, string value)>> hiddenFunc)
        {
            _hideValueFactory = hiddenFunc;

            return this;
        }

        /// <summary>
        /// 包含一个隐藏数据字段
        /// </summary>
        /// <param name="hiddenValueFunc"></param>
        /// <returns></returns>
        public TableColumn_Selector<TData> WithHiddenValue(Func<TData, (string name, string value)> hiddenValueFunc)
        {
            if (hiddenValueFunc == null)
            {
                throw new ArgumentNullException(nameof(hiddenValueFunc));
            }

            WithHiddenValues(data => new[] { hiddenValueFunc(data) });

            return this;
        }

        /// <summary>
        /// 修改时,触发的事件处理语句
        /// </summary>
        /// <param name="changedScript"></param>
        /// <returns></returns>
        public TableColumn_Selector<TData> OnChangedScript(string changedScript)
        {
            _onChangedScript = changedScript;

            return this;
        }

        public override void RenderContent(TData data, TextWriter writer)
        {
            var id = _idFactory?.Invoke(data);

            writer.WriteLine(
                $"<select {(string.IsNullOrWhiteSpace(id) ? "" : $"id=\"{id}\"")} class=\"form-control cell-select\" lay-ignore onchanged='{_onChangedScript}' name=\"{_nameFactory?.Invoke(data)}\" {(_disabled?.Invoke(data) == true ? "disabled" : "")}>");

            if (_firstItem != null)
            {
                writer.WriteLine(
                    $"<option value=\"{_firstItem.Value}\" {_firstItem.Disabled.If("disabled")}>{_firstItem.Title}</option>");
            }

            var currentValue = _selectedValue?.Invoke(data).ToStringEx();

            if (_options.HasData())
            {
                foreach (var option in _options)
                {
                    if (option==null)
                    {
                        continue;
                    }
                    writer.WriteLine(
                        $"<option value=\"{option.Value.ToStringEx()}\" {(currentValue == option.Value.ToStringEx() ? "selected" : "")} {option.Disabled.If("disabled")}>{option.Title.ToStringEx()}</option>");
                }
            }
            
            writer.WriteLine("</select>");
        }
    }

    public class TableColumn_TextboxWithButton<TData> : ColumnBase<TData>
    {
        private Func<TData, string> _valueFactory = null;
        private Func<TData, string> _nameFactory = null;
        private Func<TData, bool> _requireFactory = null;
        private Func<TData, string> _placeHolder = null;
        private Func<TData, string> _idFactory = null;
        private Func<TData, ButtonCmdBase> _btnCommand = null;
        private Func<TData,string> _buttonClickScript = null;
        private Func<TData, bool> _btnDisabled = null;
        private Func<TData, string> _iconCss = null;
        private Func<TData, (string value, string name)> _hiddenValueFunc = null;
        private Func<TData, string> _btnText = null;
        private Func<TData, bool> _textReadonly = null;
        private Func<TData, ColorPaletteEnum> _btnColor = null;

        public TableColumn_TextboxWithButton(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext, table)
        {
        }

        public TableColumn_TextboxWithButton<TData> Value(Func<TData, string> valueFactory)
        {
            _valueFactory = (data) => valueFactory(data);

            return this;
        }

        public TableColumn_TextboxWithButton<TData> Name(Func<TData, string> nameFactory)
        {
            _nameFactory = nameFactory;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> Name(string name)
        {
            _nameFactory = x => name;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> Require(Func<TData, bool> requireFactory)
        {
            _requireFactory = requireFactory;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> Placeholder(Func<TData, string> placeHolder)
        {
            _placeHolder = placeHolder;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> PlaceHolder(string placeHolder)
        {
            _placeHolder = (data) => placeHolder;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> Id(Func<TData, string> idFactory)
        {
            _idFactory = idFactory;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> ButtonDisabled(Func<TData, bool> disabledFactory)
        {
            _btnDisabled = disabledFactory;
            return this;
        }

        public TableColumn_TextboxWithButton<TData> ButtonIconCss(Func<TData, string> iconCss)
        {
            _iconCss = iconCss;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> ButtonIconCss(string iconCss)
        {
            _iconCss = (data)=> iconCss;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> ButtonText(Func<TData, string> btnText)
        {
            _btnText = btnText;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> ButtonText(string text)
        {
            _btnText = x => text;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> TextboxReadOnly(Func<TData, bool> readonlyFunc)
        {
            _textReadonly = readonlyFunc;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> TextboxReadOnly(bool allReadonly = true)
        {
            _textReadonly = x => allReadonly;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> ButtonColor(Func<TData, ColorPaletteEnum> btnColor)
        {
            _btnColor = btnColor;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> ButtonColor(ColorPaletteEnum btnColor)
        {
            _btnColor = x => btnColor;

            return this;
        }


        public TableColumn_TextboxWithButton<TData> ShowModal(Action<TData, ButtonCmd_ShowModal> config)
        {

            _btnCommand = (data) =>
            {
                var cmd = new ButtonCmd_ShowModal();

                config(data, cmd);

                return cmd;
            };

            return this;
        }

        public TableColumn_TextboxWithButton<TData> ShowDataPicker(Action<TData, ButtonCmd_ShowDataPicker> config)
        {
            _btnCommand = (data) =>
            {
                var cmd = new ButtonCmd_ShowDataPicker();
 
                config(data, cmd);

                return cmd;
            };

            return this;
        }

        public TableColumn_TextboxWithButton<TData> ExecuteCommand(Action<TData, ButtonCmd_ExecuteCmd> config)
        {
            _btnCommand = (data) =>
            {
                var cmd = new ButtonCmd_ExecuteCmd();

                config(data, cmd);

                return cmd;
            };

            return this;
        }

        public TableColumn_TextboxWithButton<TData> OnButtonClick(Func<TData, string> clickScript)
        {
            _buttonClickScript = clickScript;

            return this;
        }

        public TableColumn_TextboxWithButton<TData> WithHiddenValues(Func<TData, IEnumerable<(string name, string value)>> hiddenFunc)
        {
            _hideValueFactory = hiddenFunc;

            return this;
        }

        /// <summary>
        /// 包含一个隐藏数据字段
        /// </summary>
        /// <param name="hiddenValueFunc"></param>
        /// <returns></returns>
        public TableColumn_TextboxWithButton<TData> WithHiddenValue(Func<TData,(string name, string value)> hiddenValueFunc)
        {
            if (hiddenValueFunc==null)
            {
                throw new ArgumentNullException(nameof(hiddenValueFunc));
            }

            WithHiddenValues(data=>new []{ hiddenValueFunc (data)})  ;

            return this;
        }

        public override void RenderContent(TData data, TextWriter writer)
        {
            /*
             <div class="input-group">
                <input type="text" class="form-control" />            
                <span class="input-group-btn">
                    <button type="button" class="btn btn-info">
                    <i class="fa fa-upload"></i>
                    </button>
                </span>
             </div>
             */

            var value = _valueFactory?.Invoke(data).ToStringEx();

            var id = _idFactory?.Invoke(data);

            writer.WriteLine($"<div class=\"input-group cell-textboxwithbutton\" {(string.IsNullOrWhiteSpace(id) ? "" : $"id=\"{id}\"")}>");

            writer.WriteLine(
                $"<input lay-ignore  {(_textReadonly?.Invoke(data)==true?"readonly":"")} class=\"form-control textbox\" name=\"{_nameFactory?.Invoke(data)}\" value=\"{value}\" placeholder='{_placeHolder?.Invoke(data).ToStringEx()}' {(_requireFactory?.Invoke(data) == true ? $"required='required'" : "")}>");

            TagAttrbute tag = new TagAttrbute();

            if (_btnCommand!=null)
            {
                _btnCommand(data)?.RenderToElement(tag);
            }

            if (_buttonClickScript!=null)
            {
                tag = tag ?? new TagAttrbute();

                tag.SetOrReplaceAttr("onclick",_buttonClickScript?.Invoke(data)??"");
            }

            var iconCss = _iconCss?.Invoke(data);

            if (!string.IsNullOrWhiteSpace(iconCss))
            {
                iconCss = $"<i class=\"fa fa-{iconCss}\"></i>";
            }

            tag.Class("btn btn-" + (_btnColor?.Invoke(data) ?? ColorPaletteEnum.info).ToString());

            //if (_btnDisabled?.Invoke(data)==true)
            //{
            //    tag.SetOrReplaceAttr("disabled", "disabled");
            //}

            if (_hiddenValueFunc!=null)
            {
                var v = _hiddenValueFunc?.Invoke(data);

                writer.WriteLine($"<input type=\"hidden\" value=\"{v?.value}\" name=\"{v?.name}\"  />");
            }
            

            writer.WriteLine($"<span class=\"input-group-btn\"><button type=\"button\" {(_btnDisabled?.Invoke(data) == true ? "disabled" : "")} {tag}>{iconCss}{_btnText?.Invoke(data)??"..."}</button></span>");
            
            writer.WriteLine("</div>");
        }
    }

    public class TableColumn_DatetimePicker<TData> : ColumnBase<TData>
    {
        private Func<TData, string> _nameFactory = null;
        private Func<TData, DateTime?> _valueFactory = null;
        private Func<TData, bool> _requiredFactory = null;
        private Func<TData, string> _placeholderFactory = null;
        private Func<TData, string> _idFactory = null;
        private Func<TData, DateTime?> _minDtFactory = null;
        private Func<TData, DateTime?> _maxDtFactory = null;
        private Func<TData, DatetimePickerType> _typeFactory = x=> DatetimePickerType.Date;
        private Func<TData, string> _formatFactory = null;
        private Func<TData, bool> _readonlyFactory = x => false;
        private Func<TData, bool> _disabledFactory = x => false;

        public TableColumn_DatetimePicker(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext, table)
        {
        }

        public TableColumn_DatetimePicker<TData> Name(Func<TData, string> nameFactory)
        {
            _nameFactory = nameFactory;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Name(string name)
        {
            _nameFactory = x => name;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Value(Func<TData, DateTime?> valueFactory)
        {
            _valueFactory = valueFactory;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Value(DateTime? value)
        {
            _valueFactory = x => value;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Required(Func<TData, bool> requiredFactory)
        {
            _requiredFactory = requiredFactory;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Required(bool required = true)
        {
            _requiredFactory = x=> required;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Placeholder(Func<TData, string> placeholderFactory)
        {
            _placeholderFactory = placeholderFactory;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Placeholder(string placeholder)
        {
            _placeholderFactory = x => placeholder;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Id(Func<TData, string> idFactory)
        {
            _idFactory = idFactory;

            return this;
        }

        public TableColumn_DatetimePicker<TData> MinDt(Func<TData, DateTime?> minDtFactory)
        {
            _minDtFactory = minDtFactory;

            return this;
        }

        public TableColumn_DatetimePicker<TData> MinDt(DateTime? minDt)
        {
            _minDtFactory = x => minDt;

            return this;
        }

        public TableColumn_DatetimePicker<TData> MaxDt(Func<TData, DateTime?> maxDtFactory)
        {
            _maxDtFactory = maxDtFactory;

            return this;
        }

        public TableColumn_DatetimePicker<TData> MaxDt(DateTime? maxDt)
        {
            _maxDtFactory = x => maxDt;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Type(Func<TData, DatetimePickerType> typeFactory)
        {
            _typeFactory = typeFactory;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Type(DatetimePickerType type)
        {
            _typeFactory = x => type;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Format(Func<TData, string> formatFactory)
        {
            _formatFactory = formatFactory;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Format(string format)
        {
            _formatFactory = x => format;

            return this;
        }

        public TableColumn_DatetimePicker<TData> ReadOnly(Func<TData, bool> readonlyFactory)
        {
            _readonlyFactory = readonlyFactory;

            return this;
        }

        public TableColumn_DatetimePicker<TData> ReadOnly(bool @readonly = true)
        {
            _readonlyFactory = x => @readonly;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Disabled(Func<TData, bool> disabledFactory)
        {
            _disabledFactory = disabledFactory;

            return this;
        }

        public TableColumn_DatetimePicker<TData> Disabled(bool disabled = true)
        {
            _disabledFactory = x => disabled;

            return this;
        }

        public TableColumn_DatetimePicker<TData> CellHiddenValue(Func<TData, IEnumerable<(string name, string value)>> hiddenFunc)
        {
            _hideValueFactory = hiddenFunc;

            return this;
        }

        public override void RenderContent(TData data, TextWriter writer)
        {
            if (_typeFactory == null)
            {
                _typeFactory = x => DatetimePickerType.Date;
            }

            if (string.IsNullOrWhiteSpace(_formatFactory?.Invoke(data)))
            {
                _formatFactory = x => Utility.GetDefaultDateFormat(_typeFactory(data));
            }

            var value = _valueFactory?.Invoke(data);
            if (value.HasValue)
            {
                var minDt = _minDtFactory?.Invoke(data);
                if (minDt.HasValue && minDt.Value > value.Value)
                {
                    value = minDt.Value;
                }

                var maxDt = _maxDtFactory?.Invoke(data);
                if (maxDt.HasValue && maxDt.Value < value.Value)
                {
                    value = maxDt.Value;
                }
            }

            var datas = $"data-format=\"{_formatFactory.Invoke(data)}\" " +
                        $"data-pickertype=\"{_typeFactory.Invoke(data).ToString()}\" " +
                        $"data-maxdt=\"{_maxDtFactory?.Invoke(data).ToStringEx(_formatFactory.Invoke(data))}\" " +
                        $"data-mindt=\"{_minDtFactory?.Invoke(data).ToStringEx(_formatFactory.Invoke(data))}\" " +
                        $"data-disabled=\"{_disabledFactory?.Invoke(data).ToStringEx()}\"";

            var id = _idFactory?.Invoke(data);
            
            writer.WriteLine($"<div class=\"datetimepicker cell-datetimepicker\" {datas} {(string.IsNullOrWhiteSpace(id) ? "" : $"id=\"{id}\"")}>");
            writer.WriteLine($"<div class=\"input-group\">");

            writer.WriteLine($"<input type=\"text\" placeholder=\"{_placeholderFactory?.Invoke(data)}\" value=\"{value?.ToStringEx(_formatFactory(data))}\" {_readonlyFactory?.Invoke(data).If("readonly")} {(_requiredFactory?.Invoke(data)==true ? "required" : "")} name=\"{_nameFactory?.Invoke(data)}\"  class=\"form-control\" />");
            writer.WriteLine($"<span class=\"input-group-btn\"><button type=\"button\" class=\"btn btn-info datetimepickershow\"><i class=\"fa fa-calendar\"></i></button></span>");

            writer.WriteLine("</div>");
            writer.WriteLine("</div>");
        }
    }

    public class TableColumn_Image<TData> : ColumnBase<TData>
    {
        private Func<TData, string> _srcFunc = null;
        private Func<TData, (int width, int height)> _sizeFunc = null;
        private Func<TData, (string name, string value)> _hiddenValueFunc = null;
        private Func<TData, string> _idFunc = null;
        private Func<TData,bool> _enableUpload=null;
        private string _uploadUrl="";
        private Func<TData,string> _fieldName=null;

        public TableColumn_Image(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext, table)
        {

        }

        public TableColumn_Image<TData> Src(Func<TData, string> srcFunc)
        {
            _srcFunc = srcFunc;

            return this;
        }

        public TableColumn_Image<TData> Size(Func<TData, (int width, int height)> sizeFunc)
        {
            _sizeFunc = sizeFunc;

            return this;
        }

        public TableColumn_Image<TData> Size(Func<TData, int> sizeFunc)
        {
            if (sizeFunc != null)
            {
                _sizeFunc = x => (sizeFunc(x), sizeFunc(x));
            }

            return this;
        }

        public TableColumn_Image<TData> Size(int width, int height)
        {
            _width = $"{width}px";
            _sizeFunc = x => (width, height);
            
            return this;
        }

        public TableColumn_Image<TData> Size(int size)
        {
            _width = $"{size}px";
            _sizeFunc = x => (size, size);
            
            return this;
        }

        public TableColumn_Image<TData> Id(Func<TData, string> idFunc)
        {
            _idFunc = idFunc;

            return this;
        }

        public TableColumn_Image<TData> WithHiddenValues(Func<TData, IEnumerable<(string name, string value)>> hiddenFunc)
        {
            _hideValueFactory = hiddenFunc;

            return this;
        }

        public TableColumn_Image<TData>  EnableUpload(bool enableUpload=true){
            _enableUpload=(_)=>true;
            
            return this;
        }

        public TableColumn_Image<TData>  EnableUpload(Func<TData,bool> enableCellUpload){
            _enableUpload=enableCellUpload;
            
            return this;
        }

        public TableColumn_Image<TData> Name(Func<TData,string> fieldNameFunc){
            _fieldName=fieldNameFunc;
            return this;
        }

        public TableColumn_Image<TData> Name(string name){
            _fieldName=(data)=>name;
            return this;
        }

        public TableColumn_Image<TData> UploadUrl(string  uploadUrl){
            _uploadUrl=uploadUrl;
            return this;
        }

        /// <summary>
        /// 包含一个隐藏数据字段
        /// </summary>
        /// <param name="hiddenValueFunc"></param>
        /// <returns></returns>
        public TableColumn_Image<TData> WithHiddenValue(Func<TData, (string name, string value)> hiddenValueFunc)
        {
            if (hiddenValueFunc == null)
            {
                throw new ArgumentNullException(nameof(hiddenValueFunc));
            }

            WithHiddenValues(data => new[] { hiddenValueFunc(data) });

            return this;
        }


        public override void RenderContent(TData data, TextWriter writer)
        {
            if (_sizeFunc == null)
            {
                _sizeFunc = x => (100, 100);
            }

            var src = _srcFunc?.Invoke(data);
            var isCurrentCellEnabledUpload=_enableUpload?.Invoke(data)??false;

            if(isCurrentCellEnabledUpload){
                if(_fieldName==null)
                {
                    throw new ArgumentNullException("Name");
                }

                if (string.IsNullOrEmpty(src))
                {
                     src = AdminLTEUI.LayoutPath.ResourceBaseUrl + "/Content/images/upload_80_80.jpg";
                }
            }

            var size = _sizeFunc(data);

            var id = _idFunc?.Invoke(data);

            writer.WriteLine($"<div class=\"cell-image {(isCurrentCellEnabledUpload?"singleImageFileUploader":"")}\"   data-uploadurl=\"{(isCurrentCellEnabledUpload?_uploadUrl:"")}\" data-name=\"{(_fieldName?.Invoke(data))}\"  style=\"width:{size.width}px;height:{size.height}px;\" {(string.IsNullOrWhiteSpace(id) ? "" : $"id=\"{id}\"")}>");

            if (_fieldName!=null)
            {
                writer.WriteLine($"<input type=\"hidden\" name=\"{_fieldName(data)}\" value=\"{src}\"/>");
            }
            
            
            if (!string.IsNullOrWhiteSpace(src))
            {
                var errorSrc = $"{AdminLTEUI.LayoutPath.ResourceBaseUrl}/Content/images/picerror_{(size.width <= size.height ? "80_80" : "200_100")}.jpg";
                
                writer.WriteLine($"<img class=\"{(isCurrentCellEnabledUpload?"uploadimage":"")}\" src=\"{src}\" onerror=\"this.src='{errorSrc}';\"/><span class=\"vertical-middle\"></span>");
            }
            
            if (_hiddenValueFunc != null)
            {
                var hidden = _hiddenValueFunc(data);

                writer.WriteLine($"<input type=\"hidden\" name=\"{hidden.name}\" value=\"{hidden.value}\"/>");
            }
            
            writer.WriteLine("</div>");
        }
    }

    public class TableColumn_ButtonList<TData> : ColumnBase<TData>
    {
        private string _menuTitle = "操作";
        private List<Action<TData, ColumnButtonListConfig>> _btnList = new List<Action<TData, ColumnButtonListConfig>>(3);
        private ColorPaletteEnum _color = ColorPaletteEnum.success;
        private ColumnDropdownButtonType _type = ColumnDropdownButtonType.DropdownList;
        private ButtonListAlignEnum _alignType = ButtonListAlignEnum.Auto;

        public TableColumn_ButtonList(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext, table)
        {
            
        }

        public TableColumn_ButtonList<TData> Color(ColorPaletteEnum color)
        {
            _color = color;

            return this;
        }

        /// <summary>
        /// 按钮对齐方向,仅在Type为ButtonList时有效
        /// </summary>
        /// <param name="alignType"></param>
        /// <returns></returns>
        public TableColumn_ButtonList<TData> ButtonAlign(ButtonListAlignEnum alignType)
        {
            _alignType = alignType;
            return this;
        }

        public TableColumn_ButtonList<TData> AddButton(Action<TData, ColumnButtonListConfig> btnConfig)
        {
            _btnList.Add(btnConfig);

            return this;
        }

         public TableColumn_ButtonList<TData> AddDeleteButton(Action<TData, ColumnButtonListConfig> btnConfig=null)
        {

            _btnList.Add((data,btn)=>{btn.ForDeleteRow().Color(ColorPaletteEnum.danger).Text("删除"); btnConfig?.Invoke(data,btn);});

            return this;
        }

        /// <summary>
        /// 设置按钮类型,,可以设置下拉按钮或者横向排列按钮
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public TableColumn_ButtonList<TData> ButtonType(ColumnDropdownButtonType type)
        {
            _type = type;
            return this;
        }

        /// <summary>
        /// 下拉菜单的按钮标题
        /// </summary>
        /// <param name="title"></param>
        /// <returns></returns>
        public TableColumn_ButtonList<TData> MenuTitle(string title)
        {
            _menuTitle = title;

            return this;
        }

        public override string RenderHeader()
        {
            if (_type == ColumnDropdownButtonType.DropdownList && string.IsNullOrWhiteSpace(_width))
            {
                _width = "95px";
            }
            //else if (_type == ColumnDropdownButtonType.ButtonList && string.IsNullOrWhiteSpace(_width))
            //{
            //    _width = ((_btnList.Where(x=>x.).Count * 50) + 10) + "px";
            //}

            if (_headCellAttr != null)
            {
                _headCellAttr.Class("selectcol");
                _headCellAttr.Class(_thCss);

                if (!string.IsNullOrEmpty(_width))
                {
                    _headCellAttr.Style("width", _width.ToStringEx());
                }

                if (!string.IsNullOrEmpty(_minWidth))
                {
                    _headCellAttr.Style("min-width", _minWidth.ToStringEx());
                }

                if (!string.IsNullOrEmpty(_maxWidth))
                {
                    _headCellAttr.Style("max-width", _maxWidth.ToStringEx());
                }

                return $"<th {_headCellAttr}><span>{_title}</span></th>";
            }

            var style = $"style=\"{(string.IsNullOrWhiteSpace(_width) ? "" : $"width:{_width};")}{(string.IsNullOrWhiteSpace(_minWidth) ? "" : $"min-width:{_minWidth};")}{(string.IsNullOrWhiteSpace(_maxWidth) ? "" : $"max-width:{_maxWidth};")}\"";

            return $"<th class=\"{_thCss}\" {style}>{_title}</th>";
        }

        public override void RenderContent(TData data, TextWriter writer)
        {
            switch (_type)
            {
                case ColumnDropdownButtonType.DropdownList:
                    renderDropdownList(data, writer);
                    break;
                case ColumnDropdownButtonType.ButtonList:
                    renderButtonList(data, writer);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        private void renderDropdownList(TData data, TextWriter writer)
        {
   
            writer.WriteLine("<div class=\"btn-group table_column_dropdownlist\">");
            writer.Write($"<button type=\"button\" data-toggle=\"dropdown\" class=\"dropdown-no-float btn btn-{_color}\">{_menuTitle}</button>");
            writer.WriteLine($"<button type=\"button\" class=\"dropdown-no-float btn btn-{_color} dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"caret\"></span><span class=\"sr-only\">Toggle Dropdown</span></button>");

            writer.WriteLine("<ul class=\"dropdown-menu\" role=\"menu\">");

            foreach (var btnFunc in _btnList)
            {
                


                var config = new ColumnButtonListConfig(ViewContext);
                
                config.Css("btn ");

                btnFunc(data, config);

                if (config._hide)
                {
                    continue;
                }

                if (config._isForDeleteRow)
                {
                    config.Css("delrow");
                }

                if (config._isForDeleteRow && Table._minFixRow > 0 && Table.CurrentRowIndex < Table._minFixRow)
                {
                    continue;
                }

                config.Command?.RenderToButton(config);
                
                writer.WriteLine($"<li><a {config._disabled.If("disabled")} {config.Attributes}>{config._iconHtml}{config.GetText}</a></li>");
            }

            writer.WriteLine("</ul>");

            writer.WriteLine("</div>");
        }

        private void renderButtonList(TData data, TextWriter writer)
        {
            /*
             <div class="btn-group">
                <button type="button" class="btn btn-default"><i class="fa fa-align-left"></i></button>
                <button type="button" class="btn btn-default"><i class="fa fa-align-center"></i></button>
                <button type="button" class="btn btn-default"><i class="fa fa-align-right"></i></button>
            </div>
             */

            writer.WriteLine($"<div class=\"table_column_buttonlist {_alignType.Switch("").Case(ButtonListAlignEnum.Left, "alignleft").Case(ButtonListAlignEnum.Right, "alignright").Result}\">");

            foreach (var btnFunc in _btnList)
            {
                

                var config = new ColumnButtonListConfig(ViewContext);
                
                config.Css("btn btn-sm");

                

                btnFunc(data, config);

                if (config._hide)
                {
                    continue;
                }

                config.Css("btn-" + config._color);

                if (config._isForDeleteRow)
                {
                    config.Css("delrow");
                }

                if (config._isForDeleteRow && Table._minFixRow > 0 && Table.CurrentRowIndex < Table._minFixRow)
                {
                    continue;
                }


                switch (config._type)
                {
                    case ButtonTypeEnum.button:
                    case ButtonTypeEnum.submit:
                    {
                        config.Command?.RenderToButton(config);
                            writer.WriteLine($"<button type=\"button\" {config._disabled.If("disabled")} {config.Attributes}>{config._iconHtml}{config.GetText}</button>");
                            break;
                    }
                    case ButtonTypeEnum.link:
                    {
                        if (config.Command is ButtonCmd_Goto c)
                        {
                            config.Attr("href", c.GetUrl)
                                .Attr("target", Utility.LinkTargetToStr(c.TaragetType) );
                        }

                        writer.WriteLine(
                            $"<a {config._disabled.If("disabled")} {config.Attributes}>{config._iconHtml}{config.GetText}</a>");
                        break;
                    }
                }
                
            }

            writer.WriteLine("</div>");
        }

        public class ColumnButtonListConfig : ButtonConfigBase
        {
            internal bool _disabled = false;
            internal string _href = "";
            internal bool _isForDeleteRow = false;

            public ColumnButtonListConfig(ViewContext viewContext) : base(viewContext)
            {
            }

            public ColumnButtonListConfig Disabled(bool disable=true)
            {
                _disabled = disable;

                return this;
            }

            /// <summary>
            /// 该按钮用于删除当前行
            /// </summary>
            /// <param name="isForDeleteRow"></param>
            /// <returns></returns>
            public ColumnButtonListConfig ForDeleteRow(bool isForDeleteRow = true)
            {
                _isForDeleteRow = isForDeleteRow;

                return this;
            }
            
        }
    }

    public class TableColumn_CustomContent<TData> : ColumnBase<TData>
    {
        private Func<TData, string> _content = null;

        public TableColumn_CustomContent(ViewContext viewContext, PageCommon_Table2<TData> table) : base(viewContext, table)
        {
        }

        public TableColumn_CustomContent<TData> Content(Func<TData, HelperResult> content)
        {
            _content = (data) => content(data).ToHtmlString();

            return this;
        }

        public TableColumn_CustomContent<TData> Content(Func<TData, string> content)
        {
            _content = content;

            return this;
        }

        public TableColumn_CustomContent<TData> Content(Func<TData, ControlBase> content)
        {
            _content = (data) => { return content(data).ToStringEx(); };

            return this;
        }

        public override void RenderContent(TData data, TextWriter writer)
        {
            if (_content==null)
            {
                throw new ArgumentNullException("content");
            }

            writer.WriteLine(_content(data));
        }
    }

    


    #endregion



    #region 表格统计项




    #endregion
}